/**
 * 桥接模式（Bridge）：
 *    【将抽象部分与它的实现部分相分离】，使它们都可以独立变化。
 *    
 *    其实就是函数封装。比如要对某个dom元素添加color 和 backgroundCOlor 可以封装个changeColor函数，
 *    这样可以在多个相似逻辑中提升逻辑
 * 
 *  应用场景：
 *    在多维变化中， 桥接模式 应用更加实用。
 * 
 *   比如提取多个底层功能模块，比如提取运动，着色，说话模块。
 *   球类：可以具有运动和着色模块
 *   人类：具有 运动和说话模块
 *  
 *   这样可以实现 【模块的快速组装】 不仅仅是 【抽象与实现相分离】而是更进一步【功能与抽象分离】
 *   进而提升代码灵活性的创建对象
 * 
 *  桥接模式优点：
 *    1、分离接口和实现部分。
 *       一个实现未必不变的绑定在一个接口上， 抽象类（函数）的实现可以在运行时刻进行配置。
 *       一个对象甚至可以在运行时改变它的实现，同时 将抽象与实现进行充分解耦
 *       也有利于分层，从而产生更好的结构化系统。
 *   2、提高可扩展性。
 *   3、对客户隐藏实现细节。
 * 缺点：
 *    大量的类将导致开发成本增加
 *    同时在性能方面可能也会有所减少。
 */

/**
 * 运动模块
 */
class Speed {
    constructor(x, y) {
        this.x = x
        this.y = y
    }

    run() {
        console.log(`运动感轨迹x:${this.x}, y:${this.y}`)
    }
}

/**
 * 着色模块
 */
class Color {
    constructor(color) {
        this.color = color
    }

    draw() {
        console.log(`绘制颜色：${this.color}`)
    }
}

/**
 * 说话模块
 */
class Speak {
    constructor(words) {
        this.words = words
    }
    say() {
        console.log(`说话：说了${this.words}。`)
    }
}

/**
 * 球类
 */
class Ball {
    constructor(x, y, color) {
        this.speed = new Speed(x, y)
        this.color = new Color(color)
    }
    init() {
        this.speed.run()
        this.color.draw()
    }
}

/**
 * 人
 */
class Person {
    constructor(x, y, words) {
        this.speed = new Speed(x, y)
        this.speak = new Speak(words)
    }

    init() { 
        this.speed.run()
        this.speak.say()
    }
}

const ball = new Ball(100, 200, "#ff00ed")
ball.init()

const zhangsan = new Person(101, 203, "《时间简史》，从黑洞到大爆炸。")
zhangsan.init()